Foreword

This document tries to help you getting started with the main-engine interface. The main-engine interface is a collection of C functions that allows you to use the engine in an easy way. The only C++ code that is expected to understand, is the use of basic classes like sce::Colorf or sce::Vec3. These classes help to produce easy "write and readable code" and are very comfortable to use. The engine itself is written in C++ and its' components can be used individually. (The Sce-Edit editor uses the core engine code, and its classes.)

Rendering

You as the game programmer use the engine like a painter. The engine gives you several tools for painting: camera, buffer, rendering functions for 2d and 3d graphics.

The engine uses a double buffer system for rendering. (See the section: "Concepts, Definitions and Setup" , to get more information about the double-buffer system) You start the rendering by clearing the backbuffer. Then you define a rectangular region (=viewport) in the window that will be used for rendering. After that you call all necessary functions that render the 2d and 3d graphics. Now it is time to make the buffer visible, this is done by switching the buffers.

Resource Managment

With resources i mean graphics and sound data. To access and use these resources, the engine uses a handle based approach. (No classes are given to the game programmer!) Here is a simple example how to play a sound resource:

int backgroundMusic = -1;		// handle for the sound resource, -1 = invalid handle

void init()
{
	// register the sound resource and store its id
	backgroundMusic = sce::registerSound("bkgSong1");
	if( backgroundMusic == -1 )
	{
		/* write some message */
	}
}

void run()
{
	if( /* entering menu mode */ )
	{
		sce::playSound(backgroundMusic);	// start playing the music if entering the menu
	}
	else if( /* entering game mode */ )
	{
		sce::stopSound(backgroundMusic);	// stop playing the music if leaving the menu
	}
}



void engineStart(sce_cb init, sce_cb run, sce_cb shutdown)

The game uses this function to: The 3 params are simple C style callback functions. These functions are the entry points into the engine for your game application.
Example:
#include <windows.h>
#include "../../sce_sdk/headers/sce_engine.h"

void init()
{
	// allocate all needed resources (graphics, sounds, ...)
}

void run()
{
	// do the rendering und updating here
}

void shutdown()
{
	// free game resources, engine objects are deleted automatically
}

int APIENTRY WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR     lpCmdLine,
            int       nCmdShow)
{
	sce::engineStart(init, run, shutdown);
	return 0;
}



void engineShutDown()

Call this function, if you want to shutdown everything. After calling this function the following happens:
Example:
void update()
{
	// update input
	if( /* user wants to exit game */ )
	{
		sce::engineShutDown();
	}

	// update game

	// update rendering
}



void setAppName(const std::string& name)

Use this function to set a proper name for your application. The name can be seen in the left top corner of the window, if window mode is active.
Example:
void init()
{
	sce::setAppName("PACKMAN");

	// do initialisation
}



void resetRenderingDevice(int width, int height, bool fullscreen)

This function allowes you to choose between windowed or fullscreen mode. Use params width and height to define the needed screen resolution. The examples below shows some common screen resolutions.
Example:
void init()
{
	if( /* screen mode 800*600 windowed mode set */ )
		sce::resetRenderingDevice(800, 600, false);
	else if( /* screen mode 1024*768 windowed mode set */ )
		sce::resetRenderingDevice(1024, 768, false);
	else if( /* screen mode 1024*768 fullscreen mode set */ )
		sce::resetRenderingDevice(1024, 768, true);
}



void clearBackBuffer(const sce::Colorf& color)

The engine uses a double buffering system to do the rendering. The reason why this functionality is not done by the engine, is because it gives the game programmer a chance to do stuff like split screens.

The example shows a simple rendering loop, that handles the rendering buffers.

Example:
void run()
{
	sce::Colorf backgroundColor(1,0,0);
	sce::clearBackBuffer(backgroundColor);		// clear the backbuffer and make it completely red

	// render everything...

	sce::swapBuffers();				// make the back buffer visible, and the front buffer ready
							// for rendering
}



void swapBuffers()

See also function void clearBackBuffer(...)
Example:
see void clearBackBuffer(...)


bool isButtonDown(int key)

Check if a button on keyboard, joystick or mouse is pressed. The param key must be one of the enums defined in file: "sce_engine_common.h". The return value is true, if the button is down. (Otherwise the return value will be false.)

To push you into the right direction the code snippet shows you how a 2d game can handle the keyboard input for a spaceship moving up, down, left and right.

Example:
void run()
{
	// update input
	if( sce::isButtonDown(sce::KEY_RIGHT) )
	{
		// move the ship right
	}
	else if( sce::isButtonDown(sce::KEY_LEFT) )
	{
		// move the ship left
	}
	else if( sce::isButtonDown(sce::KEY_UP) )
	{
		// move the ship up
	}
	else if( sce::isButtonDown(sce::KEY_DOWN) )
	{
		// move the ship down
	}
}



bool isButtonUp(int key)

Basically the same as function bool isButtonDown(...).


bool isButtonUpToDown(int key)

Check if a button on keyboard, joystick or mouse is pressed. The difference between function bool isButtonDown(...) and isButtonUpToDown(...) is, that isButtonUpToDown(...) returns true if the state of the button has changed from up to down.

A good example how to use this function could be, a spaceship firing a missle. You do not want the ship to fire continously, only one shot per button push.

Example:
void run()
{
	// update input
	if( sce::isButtonUpToDown(sce::KEY_SPACE) )
	{
		// fire missle
	}
}



bool isButtonDownToUp(int key)

Basically the same as function bool isButtonDownToUp(...).


const Vec2i& getMouseAxis()

The mouse (not the mouse cursor!) is virtually placed in a xy-coordinates system. This function returns the delta of the mouse position in x and y direction if the mouse is moved.

The exmaple shows you how getMouseAxis() can be used to change the viewing angles of a free cam.

Example:
float horizontalViewAngle = 0.0f;
float verticalViewAngle = 0.0f;

void run()
{
	// update input
	if( sce::getMouseAxis().x_ != 0 )
	{
		horizontalViewAngle += sce::DEG_TO_RAD(sce::getMouseAxis().x_);
	}
	if( sce::getMouseAxis().y_ != 0 )
	{
		verticalViewAngle += sce::DEG_TO_RAD(sce::getMouseAxis().y_);
	}
}



const Vec2i& getMouseCursorPos()

Automatically the engine keeps track of cursor position changes and stores the actual position of the cursor. The cursor position is mapped into a virtual 640*480 screen.
Example:
void run()
{
	sce::Vec2i cursorPos = sce::getMouseCursorPos();

	// use "cursorPos" to do picking, handle user input for the menu, ...
}



const Vec2i& getJoystickState()

Retrieve state information of a joystick. See struct sce::JoystickState in file "sce_engine_common.h".
Example:

	



int registerCam(int viewportWidth, int viewportHeight)

The camera is used to do 2d and 3d rendering. A camera is handled like a resource object. You ask the engine for an instance, by calling function: registerCam, and retrieve a handle for this camera instance.

The example demonstrates how to register a camera, and what has to be done to do 2d and 3d rendering.

Example:
int camaId = -1;	// handle for the camera object

void init()
{
	cameraId = sce::registerCam(1024, 768);	   // ask the engine for a camera object
						   // the params 1024*768 define the viewport extensions
}

void run()
{
	sce::clearBackBuffer(sce::Colorf(0,0,0));  // clear the backbuffer with color black

	sce::setCamViewport(cameraId, sce::Colorf(0,0,0));	// prepare the scene to do rendering
	sce::setCam3d(camaId);			 // prepare for 3d rendering

	/* do 3d rendering here */

	sce::setCam2d(cameraId);       		// prepare the engine for 2d rendering

	/* do 2d rendering */

	sce::swapBuffers();	       		// make the backbuffer visible
}

void shutdown()
{
	sce::unregisterCam(cameraId);	 	// tell the engine to release the camera
					  	// (note: the engine does this by itself on shutdown,
					 	//   	  so this is not a must!)
}



void unregisterCam(int cameraId)

The camera object can also be released. This is not a must, since the engine deletes all allocated objects automatically on shutdown.

See function int registerCam(int, int) .




void setCamFrame(int cameraId, const sce::Vec3& position, const sce::Vec3& direction, const sce::Vec3& up)

Using the camera frame you are able to position the camera in space and make it aim into the wanted direction.

See section "Concepts, Definitions and Setup", to learn more about frames and cameras.

Example:
int cameraId = -1;		// handle for the camera object

void init()
{
	cameraId = sce::registerCam(1024, 768);				// register camera

         // place the cam 10 units on the negative y-axis, facing the world origin
	sce::setCamFrame(cameraId, sce::Vec3(0,-10,0), sce::Vec3(0,1,0), sce::Vec3(0,0,1));
}

void run()
{
        // update free cam

}




void setCamFrame(int cameraId, const Frame& frame)

This function is just for convenience. The example below shows you, how a free cam can be realized using keyboard and mouse input.

Example:
int cameraId = -1;		// handle for the camera object
sce::Vec3 ypr(0,0,0)		// holds yaw, pitch, roll

void init()
{
	cameraId = sce::registerCam(1024, 768);				// register camera
}

void run()
{
	// update free cam
        sce::Frame f = sce::getCamFrame(cameraId);			// get current frame of this camera

        if( sce::isButtonDown(sce::KEY_W) )				// cam moves foreward
                f.pos() = f.pos() + f.dir();
        if( sce::isButtonDown(sce::KEY_S) )				// cam moves back
                f.pos() = f.pos() - f.dir();
        if( sce::isButtonDown(sce::KEY_A) )				// cam moves left
                f.pos() = f.pos() - f.right();
        if( sce::isButtonDown(sce::KEY_D) )				// cam moves right
                f.pos() = f.pos() + f.right();

        if( sce::getMouseAxis().y_ != 0 )				// cam changes pitch
                ypr_ += sce::Vec3(0,sce::DEG_TO_RAD(-sce::getMouseAxis().y_),0);
        if( sce::getMouseAxis().x_ != 0 )				// cam changes roll
                ypr_ += sce::Vec3(sce::DEG_TO_RAD(-sce::getMouseAxis().x_),0,0);

        f.setRotation(ypr_);						// change the camera's rotation
        sce::setCamFrame(cameraId, f);					// pass new calulated frame to camera
}



const sce::Frame& getCamFrame(int cameraId)

Using this function you can access the current frame (the 4*4 matrix) of the camera. In most 3d applications the camera changes its position and orientation, so this function gives you information about the current placing of the cam.





void setCamFrustum(int cameraId, float near, float far, float left, float right, float bottom, float top)

See section "Concepts, Definitions and Setup" for more information about the frustum.

The frustum has to be set carefully. The engine uses the cam frustum for rendering optimizations. Remember, nearly all geometry that is within the frustum will be rendered. Having this is mind, it does not make sense to use the same frustum size for game acting in a dungeon and a game simulating a flight. The far value for the camera in the dungeon has to be 10-100 units. The far value for the flight game will have to be 1000-50000 units.





void getCamFrustum(int cameraId, float& near, float& far, float& left, float& right, float& bottom, float& top)

Get the values of the frustum for this camera. The six parameters are passed by referenz!




void setCamViewportExt(int cameraId, int posX, int posY, int width, int height)

Using the viewport concept, you can define multiple regions on screen, that display different scenes, or the same scene from different camera positions.

You can use multiple cameras in a scene, define different viewports for them, and do things like: splitscreens. The example shows you how to create a splitscreen window with two cameras.


Example:
int cam_1 = -1;
int cam_2 = -1;

void init()
{
	cam_1 = sce::registerCam();			// register a cam for the upper splitscreen
	cam_2 = sce::registerCam();			// register a cam for the lower splitscreen

	sce::setCamViewportExt(cam_1, 0, 0, 1024, 384);		// define the viewport for cam_1
	sce::setCamViewportExt(cam_2, 0, 384, 1024, 384);	// define the viewport for cam_2
}

void run()
{
	sce::clearBackBuffer(sce::Colorf(0,0,0));  	// clear the backbuffer with color black

         // render cam_1 viewport
	sce::setCamViewport(cam_1, sce::Colorf(0,0,0));	// prepare the scene to do rendering
	sce::setCam3d(cam_1);			 	// prepare for 3d rendering
	/* do 3d rendering here */
	sce::setCam2d(cam_1);       			// prepare the engine for 2d rendering
	/* do 2d rendering */

         // render cam_1 viewport
	sce::setCamViewport(cam_2, sce::Colorf(0,0,0));	// prepare the scene to do rendering
	sce::setCam3d(cam_2);			 	// prepare for 3d rendering
	/* do 3d rendering here again! */
	sce::setCam2d(cam_2);       			// prepare the engine for 2d rendering
	/* do 2d rendering */

	sce::swapBuffers();	       			// make the backbuffer visible
}



void getCamViewportPos(int camId, int& posX, int& posY, int& width, int& height)

Just a simple accessor function to get the current viewport values for a given camera. Note the values are passed by referenz!




void setCamViewport(int camId, const sce::Colorf&)

When doing the rendering, you have to tell the engine which viewport is the current one. Have a look at the example given in function: void setCamViewportExt()





void setCam3d(int camId)

A camera is used for 2d and 3d drawing. You have to tell the engine what kind of rendering you will do. So "setCam3d has()" to be called, before 3d rendering is done. (Basically calling this function tells the rendering hardware how the graphics data should be projected on the screen.)

See function: void setCamViewportExt()





void setCam2d(int camId)

See function: void setCam3d(int).





float getCurrentTime()

Returns the current game application time in seconds. When the engine is started and all components and managers are initialized, a timer is also started that handles synchronization. The timer starts with time: 0 seconds.





void print(const std::string& text, const sce::Vec2& destination, const sce::Vec2& charDim, const sce::Colorf& col)

Use this function to print something on screen.





float getStringWidth(const std::string& text, const sce::Vec2& dim)

Because the character size can be variable and the character set is not "monospace", the string lengths can change. This function returns the length of a string for a given character size.

This function can be used to align strings to the left or right border in a menu or in the HUD (head-up-display).





float getStringHeight(const sce::Vec2& dim)

Retruns the height of a given character size.





void dbgPrint(const std::string& text)

This function is only used in debug mode. The function only takes effect for one frame (rendering loop). It is design to print values on screen, that are not fixed. For example: if you need to know the position of a character and the character moves between sectors.

Placing this function in the 2d rendering code is not a must! It can be called from anywhere!

You can pass as many strings as you want to this function. You can not control the string position. They are printed starting in the lower left corner.
To effectively render the strings you have to call: render2dRetainedMode().





void printFPS()

Render function that prints the current frames per second, in the lower right corner. The function has to be placed in the 2d rendering code!





void render2dRetainedMode()

This function should be called after you are finished with the 2d rendering. It collects all retained 2d data, and prints it on screen. For example: if you have used dbgPrint(), now is the time that these strings are made visible.





void renderPoint(const sce::Vec2& point, const sce::Colorf& col, float pointSize)

Renders a simple spot on the virtual screen.





void renderRay2(const sce::Vec2& start, const sce::Vec2& end, const sce::Colorf& col, float lineWidth)

Renders a 2d line with a start and an end point on the virtual screen.





void renderRect(const sce::Rect& rect, const sce::Colorf& col, float lineWidth)

Renders a 2d retangle on the virtual 2d screen.





void renderPoint(const Vec3& pos, const Colorf& col, float size, bool clearAfterDraw = true)

Renders a 3d point.





void renderRay3(const sce::Vec3& start, const sce::Vec3& end, const sce::Colorf& col, float lineWidth, bool clearAfterDraw = true)

Renders a 3d line with a start and end point.





void renderSphere(const sce::Vec3& center, float radius, const sce::Colorf& col, float lineWidth, bool clearAfterDraw = true)

Renders a sphere.





void renderAABB(const sce::Vec3& min, const sce::Vec3& max, const sce::Colorf& col, float lineWidth, bool clearAfterDraw = true)

Renders an axis aligned bounding box.





void renderFrame(const sce::Frame& frame, bool clearAfterDraw = true)

Renders a frame (=coordinate system).





void renderWorldGrid(bool value)

Renders the world coordinate system and a grid. The grid shows the xy-plane. One cell is 10*10 units.





void renderFrustum(Frustum& f, bool clearAfterDraw = true)

Renders the frustum of a camera. Can be used to do some ai things. Enemy can see you or not...





void printConsole(const std::string& text)

Print some text to the engine console.





void renderConsole()

Has to be called in the 2d rendering code. Just displays the console.





bool isConsoleActive()

Flag to check if the console is visible or not.









SourceForge.net Logo